﻿using System;
using System.IO;
using System.Threading;
using System.Web;
using Codemonk.Pease.Common;

namespace Codemonk.Pease.Server.HttpServer
{
    public abstract class ResponsedAsyncResult : IResponsedAsyncResult
    {
        protected abstract IMethodInvoker<HttpContext, string> Invoker { get; }

        protected abstract ISerializater<string> Serializater { get; }

        protected abstract IAspectMonitor<HttpContext> Monitor { get; }

        protected abstract IInterfaceActivator Activator { get; }

        protected abstract IObjectDecorator<HttpContext> Decorator { get; }

        public virtual HttpContext HttpContext { get; set; }

        protected string response;
        public virtual string Response
        {
            get { return response; }
            set
            {
                response = value;
                IsCompleted = true;
            }
        }

        public virtual object AsyncState { get { return null; } }

        public virtual WaitHandle AsyncWaitHandle { get { return null; } }

        public virtual bool CompletedSynchronously { get { return false; } }

        protected bool isCompleted;
        public virtual bool IsCompleted
        {
            get { return isCompleted; }
            private set
            {
                isCompleted = value;
                if (isCompleted)
                {
                    try
                    {
                        if (Callback != null)
                            Callback(this);
                    }
                    catch { }
                }
            }
        }

        public virtual AsyncCallback Callback { get; set; }

        protected void SetErrorMessage(string message)
        {
            Response = Serializater.Serialize(new ResponseAgreement<string> { ErrorMessage = message });
        }

        public virtual void Work()
        {
            try
            {
                var context = HttpContext;
                RequestAgreement<string> request;
                using (context.Request.InputStream)
                {
                    using (StreamReader reader = new StreamReader(context.Request.InputStream))
                    {
                        string input = reader.ReadToEnd();
                        if (string.IsNullOrWhiteSpace(input))
                        {
                            SetErrorMessage("非法的方法参数");
                            return;
                        }
                        request = Serializater.Deserialize<RequestAgreement<string>>(input);
                    }
                }
                Invoker.Invoke(context, Monitor, Decorator, Activator, Serializater, request, b => Response = Serializater.Serialize(b));
            }
            catch (System.Exception ex)
            {
                SetErrorMessage(ex.Message);
            }
        }
    }
}
